{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 基于用户标签的推荐"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 导入包\n",
    "import random\n",
    "import math\n",
    "import time\n",
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一. 通用函数定义"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义装饰器，监控运行时间\n",
    "def timmer(func):\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start_time = time.time()\n",
    "        res = func(*args, **kwargs)\n",
    "        stop_time = time.time()\n",
    "        print('Func %s, run time: %s' % (func.__name__, stop_time - start_time))\n",
    "        return res\n",
    "    return wrapper"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 数据处理相关\n",
    "Delicious-2k数据集\n",
    "1. load data\n",
    "2. split data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Dataset():\n",
    "    \n",
    "    def __init__(self, fp):\n",
    "        # fp: data file path\n",
    "        self.data = self.loadData(fp)\n",
    "    \n",
    "    @timmer\n",
    "    def loadData(self, fp):\n",
    "        data = [f.strip().split('\\t')[:3] for f in open(fp).readlines()[1:]]\n",
    "        new_data = {}\n",
    "        for user, item, tag in data:\n",
    "            if user not in new_data:\n",
    "                new_data[user] = {}\n",
    "            if item not in new_data[user]:\n",
    "                new_data[user][item] = set()\n",
    "            new_data[user][item].add(tag)\n",
    "        ret = []\n",
    "        for user in new_data:\n",
    "            for item in new_data[user]:\n",
    "                ret.append((user, item, list(new_data[user][item])))\n",
    "        return ret\n",
    "    \n",
    "    @timmer\n",
    "    def splitData(self, M, k, seed=1):\n",
    "        '''\n",
    "        :params: data, 加载的所有(user, item)数据条目\n",
    "        :params: M, 划分的数目，最后需要取M折的平均\n",
    "        :params: k, 本次是第几次划分，k~[0, M)\n",
    "        :params: seed, random的种子数，对于不同的k应设置成一样的\n",
    "        :return: train, test\n",
    "        '''\n",
    "        # 按照(user, item)作为key进行划分\n",
    "        train, test = [], []\n",
    "        random.seed(seed)\n",
    "        for user, item, tags in self.data:\n",
    "            # 这里与书中的不一致，本人认为取M-1较为合理，因randint是左右都覆盖的\n",
    "            if random.randint(0, M-1) == k:  \n",
    "                test.append((user, item, tags))\n",
    "            else:\n",
    "                train.append((user, item, tags))\n",
    "\n",
    "        # 处理成字典的形式，user->set(items)\n",
    "        def convert_dict(data):\n",
    "            data_dict = {}\n",
    "            for user, item, tags in data:\n",
    "                if user not in data_dict:\n",
    "                    data_dict[user] = {}\n",
    "                data_dict[user][item] = tags\n",
    "            return data_dict\n",
    "\n",
    "        return convert_dict(train), convert_dict(test)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. 评价指标\n",
    "1. Precision\n",
    "2. Recall\n",
    "3. Coverage\n",
    "4. Diversity\n",
    "5. Popularity(Novelty)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Metric():\n",
    "    \n",
    "    def __init__(self, train, test, GetRecommendation):\n",
    "        '''\n",
    "        :params: train, 训练数据\n",
    "        :params: test, 测试数据\n",
    "        :params: GetRecommendation, 为某个用户获取推荐物品的接口函数\n",
    "        '''\n",
    "        self.train = train\n",
    "        self.test = test\n",
    "        self.GetRecommendation = GetRecommendation\n",
    "        self.recs = self.getRec()\n",
    "        \n",
    "    # 为test中的每个用户进行推荐\n",
    "    def getRec(self):\n",
    "        recs = {}\n",
    "        for user in self.test:\n",
    "            rank = self.GetRecommendation(user)\n",
    "            recs[user] = rank\n",
    "        return recs\n",
    "        \n",
    "    # 定义精确率指标计算方式\n",
    "    def precision(self):\n",
    "        all, hit = 0, 0\n",
    "        for user in self.test:\n",
    "            test_items = set(self.test[user])\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                if item in test_items:\n",
    "                    hit += 1\n",
    "            all += len(rank)\n",
    "        return round(hit / all * 100, 2)\n",
    "    \n",
    "    # 定义召回率指标计算方式\n",
    "    def recall(self):\n",
    "        all, hit = 0, 0\n",
    "        for user in self.test:\n",
    "            test_items = set(self.test[user])\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                if item in test_items:\n",
    "                    hit += 1\n",
    "            all += len(test_items)\n",
    "        return round(hit / all * 100, 2)\n",
    "    \n",
    "    # 定义覆盖率指标计算方式\n",
    "    def coverage(self):\n",
    "        all_item, recom_item = set(), set()\n",
    "        for user in self.train:\n",
    "            for item in self.train[user]:\n",
    "                all_item.add(item)\n",
    "        for user in self.test:\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                recom_item.add(item)\n",
    "        return round(len(recom_item) / len(all_item) * 100, 2)\n",
    "    \n",
    "    # 定义多样性指标计算方式\n",
    "    def diversity(self):\n",
    "        # 计算item_vec，每个tag的个数\n",
    "        item_tags = {}\n",
    "        for user in self.train:\n",
    "            for item in self.train[user]:\n",
    "                if item not in item_tags:\n",
    "                    item_tags[item] = {}\n",
    "                for tag in self.train[user][item]:\n",
    "                    if tag not in item_tags[item]:\n",
    "                        item_tags[item][tag] = 0\n",
    "                    item_tags[item][tag] += 1\n",
    "        \n",
    "        # 计算两个item的相似度\n",
    "        def CosineSim(u, v):\n",
    "            ret = 0\n",
    "            for tag in item_tags[u]:\n",
    "                if tag in item_tags[v]:\n",
    "                    ret += item_tags[u][tag] * item_tags[v][tag]\n",
    "            nu, nv = 0, 0\n",
    "            for tag in item_tags[u]:\n",
    "                nu += item_tags[u][tag] ** 2\n",
    "            for tag in item_tags[v]:\n",
    "                nv += item_tags[v][tag] ** 2\n",
    "            return ret / math.sqrt(nu * nv)\n",
    "        \n",
    "        # 计算Diversity\n",
    "        div = []\n",
    "        for user in self.test:\n",
    "            rank = self.recs[user]\n",
    "            sim, cnt = 0, 0\n",
    "            for u, _ in rank:\n",
    "                for v, _ in rank:\n",
    "                    if u == v:\n",
    "                        continue\n",
    "                    sim += CosineSim(u, v)\n",
    "                    cnt += 1\n",
    "            sim = sim / cnt if sim != 0 else 0\n",
    "            div.append(1 - sim)\n",
    "        return sum(div) / len(div)   \n",
    "    \n",
    "    # 定义新颖度指标计算方式\n",
    "    def popularity(self):\n",
    "        # 计算物品的流行度，为给这个物品打过标签的用户数\n",
    "        item_pop = {}\n",
    "        for user in self.train:\n",
    "            for item in self.train[user]:\n",
    "                if item not in item_pop:\n",
    "                    item_pop[item] = 0\n",
    "                item_pop[item] += 1\n",
    "\n",
    "        num, pop = 0, 0\n",
    "        for user in self.test:\n",
    "            rank = self.recs[user]\n",
    "            for item, score in rank:\n",
    "                # 取对数，防止因长尾问题带来的被流行物品所主导\n",
    "                pop += math.log(1 + item_pop[item])\n",
    "                num += 1\n",
    "        return round(pop / num, 6)\n",
    "    \n",
    "    def eval(self):\n",
    "        metric = {'Precision': self.precision(),\n",
    "                  'Recall': self.recall(),\n",
    "                  'Coverage': self.coverage(),\n",
    "                  'Diversity': self.diversity(),\n",
    "                  'Popularity': self.popularity()}\n",
    "        print('Metric:', metric)\n",
    "        return metric"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 二. 算法实现\n",
    "1. SimpleTagBased\n",
    "2. TagBasedTFIDF\n",
    "3. TagBasedTFIDF++\n",
    "4. TagExtend"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 基于热门标签的推荐\n",
    "def SimpleTagBased(train, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation，推荐接口函数\n",
    "    '''\n",
    "    # 统计user_tags和tag_items\n",
    "    user_tags, tag_items = {}, {}\n",
    "    for user in train:\n",
    "        user_tags[user] = {}\n",
    "        for item in train[user]:\n",
    "            for tag in train[user][item]:\n",
    "                if tag not in user_tags[user]:\n",
    "                    user_tags[user][tag] = 0\n",
    "                user_tags[user][tag] += 1\n",
    "                if tag not in tag_items:\n",
    "                    tag_items[tag] = {}\n",
    "                if item not in tag_items[tag]:\n",
    "                    tag_items[tag][item] = 0\n",
    "                tag_items[tag][item] += 1\n",
    "    \n",
    "    def GetRecommendation(user):\n",
    "        # 按照打分推荐N个未见过的\n",
    "        if user not in user_tags:\n",
    "            return []\n",
    "        seen_items = set(train[user])\n",
    "        item_score = {}\n",
    "        for tag in user_tags[user]:\n",
    "            for item in tag_items[tag]:\n",
    "                if item in seen_items:\n",
    "                    continue\n",
    "                if item not in item_score:\n",
    "                    item_score[item] = 0\n",
    "                item_score[item] += user_tags[user][tag] * tag_items[tag][item]\n",
    "        item_score = list(sorted(item_score.items(), key=lambda x: x[1], reverse=True))\n",
    "        return item_score[:N]\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 改进一：为热门标签加入惩罚项\n",
    "def TagBasedTFIDF(train, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation，推荐接口函数\n",
    "    '''\n",
    "    # 统计user_tags和tag_items\n",
    "    user_tags, tag_items = {}, {}\n",
    "    # 统计标签的热门程度，即打过此标签的不同用户数\n",
    "    tag_pop = {}\n",
    "    for user in train:\n",
    "        user_tags[user] = {}\n",
    "        for item in train[user]:\n",
    "            for tag in train[user][item]:\n",
    "                if tag not in user_tags[user]:\n",
    "                    user_tags[user][tag] = 0\n",
    "                user_tags[user][tag] += 1\n",
    "                if tag not in tag_items:\n",
    "                    tag_items[tag] = {}\n",
    "                if item not in tag_items[tag]:\n",
    "                    tag_items[tag][item] = 0\n",
    "                tag_items[tag][item] += 1\n",
    "                if tag not in tag_pop:\n",
    "                    tag_pop[tag] = set()\n",
    "                tag_pop[tag].add(user)\n",
    "    tag_pop = {k: len(v) for k, v in tag_pop.items()}\n",
    "    \n",
    "    def GetRecommendation(user):\n",
    "        # 按照打分推荐N个未见过的\n",
    "        if user not in user_tags:\n",
    "            return []\n",
    "        seen_items = set(train[user])\n",
    "        item_score = {}\n",
    "        for tag in user_tags[user]:\n",
    "            for item in tag_items[tag]:\n",
    "                if item in seen_items:\n",
    "                    continue\n",
    "                if item not in item_score:\n",
    "                    item_score[item] = 0\n",
    "                item_score[item] += user_tags[user][tag] * tag_items[tag][item] / tag_pop[tag]\n",
    "        item_score = list(sorted(item_score.items(), key=lambda x: x[1], reverse=True))\n",
    "        return item_score[:N]\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. 改进二：同时也为热门商品加入惩罚项\n",
    "def TagBasedTFIDF_Improved(train, N):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :return: GetRecommendation，推荐接口函数\n",
    "    '''\n",
    "    # 统计user_tags和tag_items\n",
    "    user_tags, tag_items = {}, {}\n",
    "    # 统计标签和物品的热门程度，即打过此标签的不同用户数，和物品对应的不同用户数\n",
    "    tag_pop, item_pop = {}, {}\n",
    "    for user in train:\n",
    "        user_tags[user] = {}\n",
    "        for item in train[user]:\n",
    "            if item not in item_pop:\n",
    "                item_pop[item] = 0\n",
    "            item_pop[item] += 1\n",
    "            for tag in train[user][item]:\n",
    "                if tag not in user_tags[user]:\n",
    "                    user_tags[user][tag] = 0\n",
    "                user_tags[user][tag] += 1\n",
    "                if tag not in tag_items:\n",
    "                    tag_items[tag] = {}\n",
    "                if item not in tag_items[tag]:\n",
    "                    tag_items[tag][item] = 0\n",
    "                tag_items[tag][item] += 1\n",
    "                if tag not in tag_pop:\n",
    "                    tag_pop[tag] = set()\n",
    "                tag_pop[tag].add(user)\n",
    "    tag_pop = {k: len(v) for k, v in tag_pop.items()}\n",
    "    \n",
    "    def GetRecommendation(user):\n",
    "        # 按照打分推荐N个未见过的\n",
    "        if user not in user_tags:\n",
    "            return []\n",
    "        seen_items = set(train[user])\n",
    "        item_score = {}\n",
    "        for tag in user_tags[user]:\n",
    "            for item in tag_items[tag]:\n",
    "                if item in seen_items:\n",
    "                    continue\n",
    "                if item not in item_score:\n",
    "                    item_score[item] = 0\n",
    "                item_score[item] += user_tags[user][tag] * tag_items[tag][item] / tag_pop[tag] / item_pop[item]\n",
    "        item_score = list(sorted(item_score.items(), key=lambda x: x[1], reverse=True))\n",
    "        return item_score[:N]\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. 基于标签改进的推荐\n",
    "def ExpandTagBased(train, N, M=20):\n",
    "    '''\n",
    "    :params: train, 训练数据集\n",
    "    :params: N, 超参数，设置取TopN推荐物品数目\n",
    "    :params: M，超参数，设置取TopM的标签填补不满M个标签的用户\n",
    "    :return: GetRecommendation，推荐接口函数\n",
    "    '''\n",
    "    \n",
    "    # 1. 计算标签之间的相似度\n",
    "    item_tag = {}\n",
    "    for user in train:\n",
    "        for item in train[user]:\n",
    "            if item not in item_tag:\n",
    "                item_tag[item] = set()\n",
    "            for tag in train[user][item]:\n",
    "                item_tag[item].add(tag)\n",
    "    tag_sim, tag_cnt = {}, {}\n",
    "    for item in item_tag:\n",
    "        for u in item_tag[item]:\n",
    "            if u not in tag_cnt:\n",
    "                tag_cnt[u] = 0\n",
    "            tag_cnt[u] += 1\n",
    "            if u not in tag_sim:\n",
    "                tag_sim[u] = {}\n",
    "            for v in item_tag[item]:\n",
    "                if u == v:\n",
    "                    continue\n",
    "                if v not in tag_sim[u]:\n",
    "                    tag_sim[u][v] = 0\n",
    "                tag_sim[u][v] += 1\n",
    "    for u in tag_sim:\n",
    "        for v in tag_sim[u]:\n",
    "            tag_sim[u][v] /= math.sqrt(tag_cnt[u] * tag_cnt[v])\n",
    "    \n",
    "    # 2. 为每个用户扩展标签\n",
    "    user_tags = {}\n",
    "    for user in train:\n",
    "        if user not in user_tags:\n",
    "            user_tags[user] = {}\n",
    "        for item in train[user]:\n",
    "            for tag in train[user][item]:\n",
    "                if tag not in user_tags[user]:\n",
    "                    user_tags[user][tag] = 0\n",
    "                user_tags[user][tag] += 1\n",
    "    expand_tags = {}\n",
    "    for user in user_tags:\n",
    "        if len(user_tags[user]) >= M:\n",
    "            expand_tags[user] = user_tags[user]\n",
    "            continue\n",
    "        # 不满M个的进行标签扩展\n",
    "        expand_tags[user] = {}\n",
    "        seen_tags = set(user_tags[user])\n",
    "        for tag in user_tags[user]:\n",
    "            for t in tag_sim[tag]:\n",
    "                if t in seen_tags:\n",
    "                    continue\n",
    "                if t not in expand_tags[user]:\n",
    "                    expand_tags[user][t] = 0\n",
    "                expand_tags[user][t] += user_tags[user][tag] * tag_sim[tag][t]\n",
    "        expand_tags[user].update(user_tags[user])\n",
    "        expand_tags[user] = dict(list(sorted(expand_tags[user].items(), key=lambda x: x[1], reverse=True))[:M])\n",
    "        \n",
    "    # 3. SimpleTagBased算法\n",
    "    tag_items = {}\n",
    "    for user in train:\n",
    "        for item in train[user]:\n",
    "            for tag in train[user][item]:\n",
    "                if tag not in tag_items:\n",
    "                    tag_items[tag] = {}\n",
    "                if item not in tag_items[tag]:\n",
    "                    tag_items[tag][item] = 0\n",
    "                tag_items[tag][item] += 1\n",
    "    \n",
    "    def GetRecommendation(user):\n",
    "        # 按照打分推荐N个未见过的\n",
    "        if user not in user_tags:\n",
    "            return []\n",
    "        seen_items = set(train[user])\n",
    "        item_score = {}\n",
    "        for tag in expand_tags[user]:\n",
    "            for item in tag_items[tag]:\n",
    "                if item in seen_items:\n",
    "                    continue\n",
    "                if item not in item_score:\n",
    "                    item_score[item] = 0\n",
    "                item_score[item] += expand_tags[user][tag] * tag_items[tag][item]\n",
    "        item_score = list(sorted(item_score.items(), key=lambda x: x[1], reverse=True))\n",
    "        return item_score[:N]\n",
    "    \n",
    "    return GetRecommendation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 三. 实验\n",
    "1. SimpleTagBased实验\n",
    "2. TagBasedTFIDF实验\n",
    "3. TagBasedTFIDF++实验\n",
    "4. TagExtend\n",
    "\n",
    "M=10, N=10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Experiment():\n",
    "    \n",
    "    def __init__(self, M, N, fp='../dataset/delicious-2k/user_taggedbookmarks.dat', rt='SimpleTagBased'):\n",
    "        '''\n",
    "        :params: M, 进行多少次实验\n",
    "        :params: N, TopN推荐物品的个数\n",
    "        :params: fp, 数据文件路径\n",
    "        :params: rt, 推荐算法类型\n",
    "        '''\n",
    "        self.M = M\n",
    "        self.N = N\n",
    "        self.fp = fp\n",
    "        self.rt = rt\n",
    "        self.alg = {'SimpleTagBased': SimpleTagBased, 'TagBasedTFIDF': TagBasedTFIDF, \\\n",
    "                    'TagBasedTFIDF_Improved': TagBasedTFIDF_Improved, 'ExtendTagBased': ExpandTagBased}\n",
    "    \n",
    "    # 定义单次实验\n",
    "    @timmer\n",
    "    def worker(self, train, test):\n",
    "        '''\n",
    "        :params: train, 训练数据集\n",
    "        :params: test, 测试数据集\n",
    "        :return: 各指标的值\n",
    "        '''\n",
    "        getRecommendation = self.alg[self.rt](train, self.N)\n",
    "        metric = Metric(train, test, getRecommendation)\n",
    "        return metric.eval()\n",
    "    \n",
    "    # 多次实验取平均\n",
    "    @timmer\n",
    "    def run(self):\n",
    "        metrics = {'Precision': 0, 'Recall': 0, \n",
    "                   'Coverage': 0, 'Diversity': 0, \n",
    "                   'Popularity': 0}\n",
    "        dataset = Dataset(self.fp)\n",
    "        for ii in range(self.M):\n",
    "            train, test = dataset.splitData(self.M, ii)\n",
    "            print('Experiment {}:'.format(ii))\n",
    "            metric = self.worker(train, test)\n",
    "            metrics = {k: metrics[k]+metric[k] for k in metrics}\n",
    "        metrics = {k: metrics[k] / self.M for k in metrics}\n",
    "        print('Average Result (M={}, N={}): {}'.format(\\\n",
    "                              self.M, self.N, metrics))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.6280088424682617\n",
      "Func splitData, run time: 0.30851316452026367\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.54, 'Coverage': 3.33, 'Diversity': 0.7889366782206686, 'Popularity': 2.341392}\n",
      "Func worker, run time: 37.870625019073486\n",
      "Func splitData, run time: 0.3097972869873047\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 0.36, 'Recall': 0.59, 'Coverage': 3.37, 'Diversity': 0.789191306584079, 'Popularity': 2.326798}\n",
      "Func worker, run time: 38.06450700759888\n",
      "Func splitData, run time: 0.32140111923217773\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 0.36, 'Recall': 0.59, 'Coverage': 3.37, 'Diversity': 0.7930642205047819, 'Popularity': 2.327752}\n",
      "Func worker, run time: 43.02850008010864\n",
      "Func splitData, run time: 0.32935285568237305\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 0.29, 'Recall': 0.48, 'Coverage': 3.35, 'Diversity': 0.7980044140029352, 'Popularity': 2.3653}\n",
      "Func worker, run time: 39.16614294052124\n",
      "Func splitData, run time: 0.1974170207977295\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 0.34, 'Recall': 0.56, 'Coverage': 3.33, 'Diversity': 0.7913038648261218, 'Popularity': 2.33633}\n",
      "Func worker, run time: 41.13529896736145\n",
      "Func splitData, run time: 0.19643640518188477\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 3.29, 'Diversity': 0.7897780704681152, 'Popularity': 2.346427}\n",
      "Func worker, run time: 38.96295094490051\n",
      "Func splitData, run time: 0.19998574256896973\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 0.35, 'Recall': 0.56, 'Coverage': 3.48, 'Diversity': 0.7947467303677718, 'Popularity': 2.305821}\n",
      "Func worker, run time: 40.37690997123718\n",
      "Func splitData, run time: 0.19191503524780273\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 3.39, 'Diversity': 0.7909845940006351, 'Popularity': 2.362614}\n",
      "Func worker, run time: 41.105441093444824\n",
      "Func splitData, run time: 0.1934211254119873\n",
      "Experiment 8:\n",
      "Metric: {'Precision': 0.34, 'Recall': 0.55, 'Coverage': 3.37, 'Diversity': 0.7895494174800041, 'Popularity': 2.343617}\n",
      "Func worker, run time: 39.65980076789856\n",
      "Func splitData, run time: 0.1929779052734375\n",
      "Experiment 9:\n",
      "Metric: {'Precision': 0.34, 'Recall': 0.56, 'Coverage': 3.33, 'Diversity': 0.7882350055007459, 'Popularity': 2.340735}\n",
      "Func worker, run time: 41.376152992248535\n",
      "Average Result (M=10, N=10): {'Precision': 0.33699999999999997, 'Recall': 0.5529999999999999, 'Coverage': 3.3609999999999998, 'Diversity': 0.7913794301955859, 'Popularity': 2.3396786}\n",
      "Func run, run time: 404.8816478252411\n"
     ]
    }
   ],
   "source": [
    "# 1. SimpleTagBased实验\n",
    "M, N = 10, 10\n",
    "exp = Experiment(M, N, rt='SimpleTagBased')\n",
    "exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.6277968883514404\n",
      "Func splitData, run time: 0.27590298652648926\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 0.38, 'Recall': 0.62, 'Coverage': 16.84, 'Diversity': 0.8817864660115259, 'Popularity': 1.324191}\n",
      "Func worker, run time: 46.15612602233887\n",
      "Func splitData, run time: 0.31597304344177246\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 0.39, 'Recall': 0.64, 'Coverage': 16.95, 'Diversity': 0.8826858063646551, 'Popularity': 1.316902}\n",
      "Func worker, run time: 43.69584107398987\n",
      "Func splitData, run time: 0.24825787544250488\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 0.35, 'Recall': 0.58, 'Coverage': 16.95, 'Diversity': 0.8810856212597441, 'Popularity': 1.32838}\n",
      "Func worker, run time: 43.3360550403595\n",
      "Func splitData, run time: 0.26052021980285645\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 0.3, 'Recall': 0.5, 'Coverage': 16.98, 'Diversity': 0.8852701028022301, 'Popularity': 1.324043}\n",
      "Func worker, run time: 43.02037310600281\n",
      "Func splitData, run time: 0.26059913635253906\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 0.39, 'Recall': 0.65, 'Coverage': 16.93, 'Diversity': 0.8839700173444075, 'Popularity': 1.318708}\n",
      "Func worker, run time: 44.03740382194519\n",
      "Func splitData, run time: 0.25109100341796875\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 0.36, 'Recall': 0.59, 'Coverage': 16.86, 'Diversity': 0.8819926728499792, 'Popularity': 1.332067}\n",
      "Func worker, run time: 43.196900844573975\n",
      "Func splitData, run time: 0.26158785820007324\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 0.36, 'Recall': 0.58, 'Coverage': 17.06, 'Diversity': 0.8857461664078716, 'Popularity': 1.317056}\n",
      "Func worker, run time: 43.58964991569519\n",
      "Func splitData, run time: 0.26162195205688477\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 0.35, 'Recall': 0.58, 'Coverage': 17.08, 'Diversity': 0.8821745724171214, 'Popularity': 1.331707}\n",
      "Func worker, run time: 43.189525842666626\n",
      "Func splitData, run time: 0.23992609977722168\n",
      "Experiment 8:\n",
      "Metric: {'Precision': 0.31, 'Recall': 0.51, 'Coverage': 16.89, 'Diversity': 0.8827909053583793, 'Popularity': 1.327498}\n",
      "Func worker, run time: 45.02846622467041\n",
      "Func splitData, run time: 0.25911593437194824\n",
      "Experiment 9:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 16.98, 'Diversity': 0.8824719933838076, 'Popularity': 1.323312}\n",
      "Func worker, run time: 43.965688705444336\n",
      "Average Result (M=10, N=10): {'Precision': 0.352, 'Recall': 0.5799999999999998, 'Coverage': 16.952, 'Diversity': 0.8829974324199723, 'Popularity': 1.3243864}\n",
      "Func run, run time: 443.55260705947876\n"
     ]
    }
   ],
   "source": [
    "# 2. TagBasedTFIDF实验\n",
    "M, N = 10, 10\n",
    "exp = Experiment(M, N, rt='TagBasedTFIDF')\n",
    "exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.2623248100280762\n",
      "Func splitData, run time: 0.2863779067993164\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 0.14, 'Recall': 0.23, 'Coverage': 19.4, 'Diversity': 0.859877838307336, 'Popularity': 0.786183}\n",
      "Func worker, run time: 54.93890690803528\n",
      "Func splitData, run time: 0.2523970603942871\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 0.16, 'Recall': 0.27, 'Coverage': 19.36, 'Diversity': 0.8617994094261496, 'Popularity': 0.785819}\n",
      "Func worker, run time: 54.65705108642578\n",
      "Func splitData, run time: 0.26293516159057617\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 0.18, 'Recall': 0.3, 'Coverage': 19.48, 'Diversity': 0.861349178757724, 'Popularity': 0.787125}\n",
      "Func worker, run time: 54.77145004272461\n",
      "Func splitData, run time: 0.2572140693664551\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 0.15, 'Recall': 0.24, 'Coverage': 19.32, 'Diversity': 0.8633524800153738, 'Popularity': 0.78599}\n",
      "Func worker, run time: 54.72025799751282\n",
      "Func splitData, run time: 0.2647433280944824\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 0.21, 'Recall': 0.34, 'Coverage': 19.38, 'Diversity': 0.8611766478285409, 'Popularity': 0.786397}\n",
      "Func worker, run time: 54.61092400550842\n",
      "Func splitData, run time: 0.2570078372955322\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 0.16, 'Recall': 0.27, 'Coverage': 19.36, 'Diversity': 0.8607577942073997, 'Popularity': 0.786923}\n",
      "Func worker, run time: 54.64287829399109\n",
      "Func splitData, run time: 0.25312089920043945\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 0.16, 'Recall': 0.26, 'Coverage': 19.43, 'Diversity': 0.8622121035638752, 'Popularity': 0.784275}\n",
      "Func worker, run time: 54.19543790817261\n",
      "Func splitData, run time: 0.25305795669555664\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 0.16, 'Recall': 0.26, 'Coverage': 19.57, 'Diversity': 0.8625286276619254, 'Popularity': 0.785651}\n",
      "Func worker, run time: 54.9225959777832\n",
      "Func splitData, run time: 0.24744105339050293\n",
      "Experiment 8:\n",
      "Metric: {'Precision': 0.15, 'Recall': 0.24, 'Coverage': 19.41, 'Diversity': 0.8605756591696193, 'Popularity': 0.784442}\n",
      "Func worker, run time: 56.0502827167511\n",
      "Func splitData, run time: 0.25081896781921387\n",
      "Experiment 9:\n",
      "Metric: {'Precision': 0.16, 'Recall': 0.26, 'Coverage': 19.4, 'Diversity': 0.8585022350741194, 'Popularity': 0.785889}\n",
      "Func worker, run time: 54.0096640586853\n",
      "Average Result (M=10, N=10): {'Precision': 0.16299999999999998, 'Recall': 0.267, 'Coverage': 19.410999999999998, 'Diversity': 0.8612131974012064, 'Popularity': 0.7858693999999999}\n",
      "Func run, run time: 551.4401750564575\n"
     ]
    }
   ],
   "source": [
    "# 3. TagBasedTFIDF++实验\n",
    "M, N = 10, 10\n",
    "exp = Experiment(M, N, rt='TagBasedTFIDF_Improved')\n",
    "exp.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Func loadData, run time: 1.888315200805664\n",
      "Func splitData, run time: 0.18341422080993652\n",
      "Experiment 0:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.54, 'Coverage': 3.37, 'Diversity': 0.7882770482685956, 'Popularity': 2.338341}\n",
      "Func worker, run time: 45.58587598800659\n",
      "Func splitData, run time: 0.342771053314209\n",
      "Experiment 1:\n",
      "Metric: {'Precision': 0.37, 'Recall': 0.61, 'Coverage': 3.45, 'Diversity': 0.7884184200805971, 'Popularity': 2.323208}\n",
      "Func worker, run time: 43.79095387458801\n",
      "Func splitData, run time: 0.18767595291137695\n",
      "Experiment 2:\n",
      "Metric: {'Precision': 0.36, 'Recall': 0.6, 'Coverage': 3.47, 'Diversity': 0.7920836566910633, 'Popularity': 2.323179}\n",
      "Func worker, run time: 45.01177382469177\n",
      "Func splitData, run time: 0.3437650203704834\n",
      "Experiment 3:\n",
      "Metric: {'Precision': 0.29, 'Recall': 0.47, 'Coverage': 3.39, 'Diversity': 0.7975400160363582, 'Popularity': 2.361645}\n",
      "Func worker, run time: 40.95514512062073\n",
      "Func splitData, run time: 0.3429849147796631\n",
      "Experiment 4:\n",
      "Metric: {'Precision': 0.37, 'Recall': 0.62, 'Coverage': 3.4, 'Diversity': 0.7909206637230392, 'Popularity': 2.333121}\n",
      "Func worker, run time: 41.210543155670166\n",
      "Func splitData, run time: 0.32721614837646484\n",
      "Experiment 5:\n",
      "Metric: {'Precision': 0.34, 'Recall': 0.56, 'Coverage': 3.33, 'Diversity': 0.788432348430914, 'Popularity': 2.344057}\n",
      "Func worker, run time: 41.1824209690094\n",
      "Func splitData, run time: 0.19087624549865723\n",
      "Experiment 6:\n",
      "Metric: {'Precision': 0.37, 'Recall': 0.6, 'Coverage': 3.52, 'Diversity': 0.7933734279462265, 'Popularity': 2.302654}\n",
      "Func worker, run time: 44.1220920085907\n",
      "Func splitData, run time: 0.3399050235748291\n",
      "Experiment 7:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 3.45, 'Diversity': 0.7899962076862624, 'Popularity': 2.359363}\n",
      "Func worker, run time: 41.13612079620361\n",
      "Func splitData, run time: 0.3469550609588623\n",
      "Experiment 8:\n",
      "Metric: {'Precision': 0.33, 'Recall': 0.53, 'Coverage': 3.41, 'Diversity': 0.7877338070843662, 'Popularity': 2.340181}\n",
      "Func worker, run time: 41.45753598213196\n",
      "Func splitData, run time: 0.34490013122558594\n",
      "Experiment 9:\n",
      "Metric: {'Precision': 0.35, 'Recall': 0.58, 'Coverage': 3.36, 'Diversity': 0.7874806960384569, 'Popularity': 2.337171}\n",
      "Func worker, run time: 41.51561903953552\n",
      "Average Result (M=10, N=10): {'Precision': 0.34400000000000003, 'Recall': 0.5660000000000001, 'Coverage': 3.4150000000000005, 'Diversity': 0.7904256291985878, 'Popularity': 2.336292}\n",
      "Func run, run time: 430.87147402763367\n"
     ]
    }
   ],
   "source": [
    "# 4. TagExtend实验\n",
    "M, N = 10, 10\n",
    "exp = Experiment(M, N, rt='ExtendTagBased')\n",
    "exp.run()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四. 实验结果\n",
    "1. SimpleTagBased实验\n",
    "\n",
    "    Running time: 404.8816478252411\n",
    "    \n",
    "    Average Result (M=10, N=10): {'Precision': 0.33699999999999997, 'Recall': 0.5529999999999999, 'Coverage': 3.3609999999999998, 'Diversity': 0.7913794301955859, 'Popularity': 2.3396786}\n",
    "     \n",
    "2. TagBasedTFIDF实验\n",
    "    \n",
    "    Running time: 443.55260705947876\n",
    "    \n",
    "    Average Result (M=10, N=10): {'Precision': 0.352, 'Recall': 0.5799999999999998, 'Coverage': 16.952, 'Diversity': 0.8829974324199723, 'Popularity': 1.3243864}\n",
    "     \n",
    "3. TagBasedTFIDF_Improved实验\n",
    "    \n",
    "    Running time: 551.4401750564575\n",
    "    \n",
    "    Average Result (M=10, N=10): {'Precision': 0.16299999999999998, 'Recall': 0.267, 'Coverage': 19.410999999999998, 'Diversity': 0.8612131974012064, 'Popularity': 0.7858693999999999}\n",
    "\n",
    "4. ExtendTagBased实验\n",
    "\n",
    "    Running time: 430.87147402763367\n",
    "    \n",
    "    Average Result (M=10, N=10): {'Precision': 0.34400000000000003, 'Recall': 0.5660000000000001, 'Coverage': 3.4150000000000005, 'Diversity': 0.7904256291985878, 'Popularity': 2.336292}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 附：运行日志（请双击看）\n",
    "\n",
    "1. SimpleTagBased实验\n",
    "Func loadData, run time: 1.6280088424682617\n",
    "Func splitData, run time: 0.30851316452026367\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.54, 'Coverage': 3.33, 'Diversity': 0.7889366782206686, 'Popularity': 2.341392}\n",
    "Func worker, run time: 37.870625019073486\n",
    "Func splitData, run time: 0.3097972869873047\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 0.36, 'Recall': 0.59, 'Coverage': 3.37, 'Diversity': 0.789191306584079, 'Popularity': 2.326798}\n",
    "Func worker, run time: 38.06450700759888\n",
    "Func splitData, run time: 0.32140111923217773\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 0.36, 'Recall': 0.59, 'Coverage': 3.37, 'Diversity': 0.7930642205047819, 'Popularity': 2.327752}\n",
    "Func worker, run time: 43.02850008010864\n",
    "Func splitData, run time: 0.32935285568237305\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 0.29, 'Recall': 0.48, 'Coverage': 3.35, 'Diversity': 0.7980044140029352, 'Popularity': 2.3653}\n",
    "Func worker, run time: 39.16614294052124\n",
    "Func splitData, run time: 0.1974170207977295\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 0.34, 'Recall': 0.56, 'Coverage': 3.33, 'Diversity': 0.7913038648261218, 'Popularity': 2.33633}\n",
    "Func worker, run time: 41.13529896736145\n",
    "Func splitData, run time: 0.19643640518188477\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 3.29, 'Diversity': 0.7897780704681152, 'Popularity': 2.346427}\n",
    "Func worker, run time: 38.96295094490051\n",
    "Func splitData, run time: 0.19998574256896973\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 0.35, 'Recall': 0.56, 'Coverage': 3.48, 'Diversity': 0.7947467303677718, 'Popularity': 2.305821}\n",
    "Func worker, run time: 40.37690997123718\n",
    "Func splitData, run time: 0.19191503524780273\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 3.39, 'Diversity': 0.7909845940006351, 'Popularity': 2.362614}\n",
    "Func worker, run time: 41.105441093444824\n",
    "Func splitData, run time: 0.1934211254119873\n",
    "Experiment 8:\n",
    "Metric: {'Precision': 0.34, 'Recall': 0.55, 'Coverage': 3.37, 'Diversity': 0.7895494174800041, 'Popularity': 2.343617}\n",
    "Func worker, run time: 39.65980076789856\n",
    "Func splitData, run time: 0.1929779052734375\n",
    "Experiment 9:\n",
    "Metric: {'Precision': 0.34, 'Recall': 0.56, 'Coverage': 3.33, 'Diversity': 0.7882350055007459, 'Popularity': 2.340735}\n",
    "Func worker, run time: 41.376152992248535\n",
    "Average Result (M=10, N=10): {'Precision': 0.33699999999999997, 'Recall': 0.5529999999999999, 'Coverage': 3.3609999999999998, 'Diversity': 0.7913794301955859, 'Popularity': 2.3396786}\n",
    "Func run, run time: 404.8816478252411\n",
    "\n",
    "2. TagBasedTFIDF实验\n",
    "Func loadData, run time: 1.6277968883514404\n",
    "Func splitData, run time: 0.27590298652648926\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 0.38, 'Recall': 0.62, 'Coverage': 16.84, 'Diversity': 0.8817864660115259, 'Popularity': 1.324191}\n",
    "Func worker, run time: 46.15612602233887\n",
    "Func splitData, run time: 0.31597304344177246\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 0.39, 'Recall': 0.64, 'Coverage': 16.95, 'Diversity': 0.8826858063646551, 'Popularity': 1.316902}\n",
    "Func worker, run time: 43.69584107398987\n",
    "Func splitData, run time: 0.24825787544250488\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 0.35, 'Recall': 0.58, 'Coverage': 16.95, 'Diversity': 0.8810856212597441, 'Popularity': 1.32838}\n",
    "Func worker, run time: 43.3360550403595\n",
    "Func splitData, run time: 0.26052021980285645\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 0.3, 'Recall': 0.5, 'Coverage': 16.98, 'Diversity': 0.8852701028022301, 'Popularity': 1.324043}\n",
    "Func worker, run time: 43.02037310600281\n",
    "Func splitData, run time: 0.26059913635253906\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 0.39, 'Recall': 0.65, 'Coverage': 16.93, 'Diversity': 0.8839700173444075, 'Popularity': 1.318708}\n",
    "Func worker, run time: 44.03740382194519\n",
    "Func splitData, run time: 0.25109100341796875\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 0.36, 'Recall': 0.59, 'Coverage': 16.86, 'Diversity': 0.8819926728499792, 'Popularity': 1.332067}\n",
    "Func worker, run time: 43.196900844573975\n",
    "Func splitData, run time: 0.26158785820007324\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 0.36, 'Recall': 0.58, 'Coverage': 17.06, 'Diversity': 0.8857461664078716, 'Popularity': 1.317056}\n",
    "Func worker, run time: 43.58964991569519\n",
    "Func splitData, run time: 0.26162195205688477\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 0.35, 'Recall': 0.58, 'Coverage': 17.08, 'Diversity': 0.8821745724171214, 'Popularity': 1.331707}\n",
    "Func worker, run time: 43.189525842666626\n",
    "Func splitData, run time: 0.23992609977722168\n",
    "Experiment 8:\n",
    "Metric: {'Precision': 0.31, 'Recall': 0.51, 'Coverage': 16.89, 'Diversity': 0.8827909053583793, 'Popularity': 1.327498}\n",
    "Func worker, run time: 45.02846622467041\n",
    "Func splitData, run time: 0.25911593437194824\n",
    "Experiment 9:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 16.98, 'Diversity': 0.8824719933838076, 'Popularity': 1.323312}\n",
    "Func worker, run time: 43.965688705444336\n",
    "Average Result (M=10, N=10): {'Precision': 0.352, 'Recall': 0.5799999999999998, 'Coverage': 16.952, 'Diversity': 0.8829974324199723, 'Popularity': 1.3243864}\n",
    "Func run, run time: 443.55260705947876\n",
    "\n",
    "3. TagBasedTFIDF++实验\n",
    "Func loadData, run time: 1.2623248100280762\n",
    "Func splitData, run time: 0.2863779067993164\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 0.14, 'Recall': 0.23, 'Coverage': 19.4, 'Diversity': 0.859877838307336, 'Popularity': 0.786183}\n",
    "Func worker, run time: 54.93890690803528\n",
    "Func splitData, run time: 0.2523970603942871\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 0.16, 'Recall': 0.27, 'Coverage': 19.36, 'Diversity': 0.8617994094261496, 'Popularity': 0.785819}\n",
    "Func worker, run time: 54.65705108642578\n",
    "Func splitData, run time: 0.26293516159057617\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 0.18, 'Recall': 0.3, 'Coverage': 19.48, 'Diversity': 0.861349178757724, 'Popularity': 0.787125}\n",
    "Func worker, run time: 54.77145004272461\n",
    "Func splitData, run time: 0.2572140693664551\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 0.15, 'Recall': 0.24, 'Coverage': 19.32, 'Diversity': 0.8633524800153738, 'Popularity': 0.78599}\n",
    "Func worker, run time: 54.72025799751282\n",
    "Func splitData, run time: 0.2647433280944824\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 0.21, 'Recall': 0.34, 'Coverage': 19.38, 'Diversity': 0.8611766478285409, 'Popularity': 0.786397}\n",
    "Func worker, run time: 54.61092400550842\n",
    "Func splitData, run time: 0.2570078372955322\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 0.16, 'Recall': 0.27, 'Coverage': 19.36, 'Diversity': 0.8607577942073997, 'Popularity': 0.786923}\n",
    "Func worker, run time: 54.64287829399109\n",
    "Func splitData, run time: 0.25312089920043945\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 0.16, 'Recall': 0.26, 'Coverage': 19.43, 'Diversity': 0.8622121035638752, 'Popularity': 0.784275}\n",
    "Func worker, run time: 54.19543790817261\n",
    "Func splitData, run time: 0.25305795669555664\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 0.16, 'Recall': 0.26, 'Coverage': 19.57, 'Diversity': 0.8625286276619254, 'Popularity': 0.785651}\n",
    "Func worker, run time: 54.9225959777832\n",
    "Func splitData, run time: 0.24744105339050293\n",
    "Experiment 8:\n",
    "Metric: {'Precision': 0.15, 'Recall': 0.24, 'Coverage': 19.41, 'Diversity': 0.8605756591696193, 'Popularity': 0.784442}\n",
    "Func worker, run time: 56.0502827167511\n",
    "Func splitData, run time: 0.25081896781921387\n",
    "Experiment 9:\n",
    "Metric: {'Precision': 0.16, 'Recall': 0.26, 'Coverage': 19.4, 'Diversity': 0.8585022350741194, 'Popularity': 0.785889}\n",
    "Func worker, run time: 54.0096640586853\n",
    "Average Result (M=10, N=10): {'Precision': 0.16299999999999998, 'Recall': 0.267, 'Coverage': 19.410999999999998, 'Diversity': 0.8612131974012064, 'Popularity': 0.7858693999999999}\n",
    "Func run, run time: 551.4401750564575\n",
    "\n",
    "4. ExtendTagBased实验\n",
    "Func loadData, run time: 1.888315200805664\n",
    "Func splitData, run time: 0.18341422080993652\n",
    "Experiment 0:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.54, 'Coverage': 3.37, 'Diversity': 0.7882770482685956, 'Popularity': 2.338341}\n",
    "Func worker, run time: 45.58587598800659\n",
    "Func splitData, run time: 0.342771053314209\n",
    "Experiment 1:\n",
    "Metric: {'Precision': 0.37, 'Recall': 0.61, 'Coverage': 3.45, 'Diversity': 0.7884184200805971, 'Popularity': 2.323208}\n",
    "Func worker, run time: 43.79095387458801\n",
    "Func splitData, run time: 0.18767595291137695\n",
    "Experiment 2:\n",
    "Metric: {'Precision': 0.36, 'Recall': 0.6, 'Coverage': 3.47, 'Diversity': 0.7920836566910633, 'Popularity': 2.323179}\n",
    "Func worker, run time: 45.01177382469177\n",
    "Func splitData, run time: 0.3437650203704834\n",
    "Experiment 3:\n",
    "Metric: {'Precision': 0.29, 'Recall': 0.47, 'Coverage': 3.39, 'Diversity': 0.7975400160363582, 'Popularity': 2.361645}\n",
    "Func worker, run time: 40.95514512062073\n",
    "Func splitData, run time: 0.3429849147796631\n",
    "Experiment 4:\n",
    "Metric: {'Precision': 0.37, 'Recall': 0.62, 'Coverage': 3.4, 'Diversity': 0.7909206637230392, 'Popularity': 2.333121}\n",
    "Func worker, run time: 41.210543155670166\n",
    "Func splitData, run time: 0.32721614837646484\n",
    "Experiment 5:\n",
    "Metric: {'Precision': 0.34, 'Recall': 0.56, 'Coverage': 3.33, 'Diversity': 0.788432348430914, 'Popularity': 2.344057}\n",
    "Func worker, run time: 41.1824209690094\n",
    "Func splitData, run time: 0.19087624549865723\n",
    "Experiment 6:\n",
    "Metric: {'Precision': 0.37, 'Recall': 0.6, 'Coverage': 3.52, 'Diversity': 0.7933734279462265, 'Popularity': 2.302654}\n",
    "Func worker, run time: 44.1220920085907\n",
    "Func splitData, run time: 0.3399050235748291\n",
    "Experiment 7:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.55, 'Coverage': 3.45, 'Diversity': 0.7899962076862624, 'Popularity': 2.359363}\n",
    "Func worker, run time: 41.13612079620361\n",
    "Func splitData, run time: 0.3469550609588623\n",
    "Experiment 8:\n",
    "Metric: {'Precision': 0.33, 'Recall': 0.53, 'Coverage': 3.41, 'Diversity': 0.7877338070843662, 'Popularity': 2.340181}\n",
    "Func worker, run time: 41.45753598213196\n",
    "Func splitData, run time: 0.34490013122558594\n",
    "Experiment 9:\n",
    "Metric: {'Precision': 0.35, 'Recall': 0.58, 'Coverage': 3.36, 'Diversity': 0.7874806960384569, 'Popularity': 2.337171}\n",
    "Func worker, run time: 41.51561903953552\n",
    "Average Result (M=10, N=10): {'Precision': 0.34400000000000003, 'Recall': 0.5660000000000001, 'Coverage': 3.4150000000000005, 'Diversity': 0.7904256291985878, 'Popularity': 2.336292}\n",
    "Func run, run time: 430.87147402763367"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
